package com.sh.data.engine.application.service.integration;

import com.sh.data.engine.application.model.dto.base.PagerResponse;
import com.sh.data.engine.application.model.dto.integration.*;
import com.sh.data.engine.application.model.mapper.integration.*;
import com.sh.data.engine.application.model.request.integration.*;
import com.sh.data.engine.common.exception.BusinessException;
import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.base.model.PageResult;
import com.sh.data.engine.domain.integration.api.http.model.domain.TaskDomain;
import com.sh.data.engine.domain.integration.api.http.model.domain.TaskOverviewDomain;
import com.sh.data.engine.domain.integration.api.http.model.domain.TestApiHttpDomain;
import com.sh.data.engine.domain.integration.api.http.model.param.ApiHttpAuthParam;
import com.sh.data.engine.domain.integration.api.http.model.param.ApiHttpRequestBodyParam;
import com.sh.data.engine.domain.integration.api.http.model.param.ApiHttpSaveParam;
import com.sh.data.engine.domain.integration.api.http.model.param.TestApiHttpParam;
import com.sh.data.engine.domain.integration.api.http.service.ApiHttpService;
import com.sh.data.engine.domain.integration.api.taskconfig.model.domain.ApiLogDomain;
import com.sh.data.engine.domain.integration.api.taskconfig.model.domain.JarUploadResultDomain;
import com.sh.data.engine.domain.integration.api.taskconfig.model.domain.TaskConfigDomain;
import com.sh.data.engine.domain.integration.api.taskconfig.model.domain.TaskRecordDomain;
import com.sh.data.engine.domain.integration.api.taskconfig.model.param.ExpressionParam;
import com.sh.data.engine.domain.integration.api.taskconfig.model.param.PreviewExpressParam;
import com.sh.data.engine.domain.integration.api.taskconfig.model.param.TaskConfigParam;
import com.sh.data.engine.domain.integration.api.taskconfig.model.param.TaskRecordParam;
import com.sh.data.engine.domain.integration.datasource.model.domain.DataSourceDomain;
import com.sh.data.engine.domain.shims.db.model.FieldInfoDomain;
import com.sh.data.engine.domain.shims.db.model.TableInfoDomain;
import com.sh.data.engine.domain.util.ConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

/**
 * @author: mengzheng.mhc
 * @date: 2024/6/27 13:56
 */
@Slf4j
@Service
public class ApiHttpApplicationService {

    @Autowired
    private ApiHttpService apiHttpService;

    @Autowired
    private HttpTaskOverviewDTOMapper taskOverviewDTOMapper;

    @Autowired
    private TaskItemDTOPageMapper taskItemDTOPageMapper;

    @Autowired
    private HttpTaskDTOMapper taskDTOMapper;

    @Autowired
    private TestApiDTOMapper testApiDTOMapper;

    @Autowired
    private UploadJarDTOMapper uploadJarDTOMapper;
    @Autowired
    private TaskRecordDTOPageMapper taskRecordDTOPageMapper;

    public TaskOverviewDTO getOverview(Long projectId) {
        TaskOverviewDomain overview = apiHttpService.getOverview(projectId);
        return taskOverviewDTOMapper.map(overview);
    }

    public PagerResponse<TaskItemDTO> getTaskPage(Integer pageNum, Integer pageSize, Integer status, String search) {
        var pageResult = apiHttpService.getTaskPage(pageNum, pageSize, status, search);
        return taskItemDTOPageMapper.toPageResponse(pageResult);
    }

    public HttpTaskDTO getTaskById(Long id) {
        TaskDomain taskDomain = apiHttpService.getTaskById(id);
        HttpTaskDTO taskDTO = taskDTOMapper.map(taskDomain);

        TaskDomain.TestAPiHttpRequest sourceApiHttpRequest = taskDomain.getApiHttpRequest();
        TestApiHttpRequest testAPiHttpRequest =
            ConvertUtil.copyProperties(sourceApiHttpRequest, TestApiHttpRequest.class);
        testAPiHttpRequest.setApiHttpAuthParam(
            ConvertUtil.copyProperties(
                sourceApiHttpRequest.getApiHttpAuthParam(), TestApiHttpRequest.ApiHttpAuthParam.class));

        // 请求体
        TaskDomain.TestAPiHttpRequest.ApiHttpRequestBodyParam sourceBodyParam =
            sourceApiHttpRequest.getApiHttpRequestBodyParam();
        TestApiHttpRequest.ApiHttpRequestBodyParam bodyParam =
            ConvertUtil.copyProperties(
                sourceBodyParam, TestApiHttpRequest.ApiHttpRequestBodyParam.class);

        if (CollectionUtils.isNotEmpty(sourceBodyParam.getFormParams())) {
            bodyParam.setFormParams(
                ConvertUtil.copyProperties(
                    sourceBodyParam.getFormParams(),
                    TestApiHttpRequest.ApiHttpRequestBodyParam.FormParam.class));
        }
        testAPiHttpRequest.setApiHttpRequestBodyParam(bodyParam);

        taskDTO.setApiHttpRequest(testAPiHttpRequest);

        TaskDomain.PreviewExpressRequest sourcePreviewExpressRequest =
            taskDomain.getPreviewExpressRequest();
        PreviewExpressRequest previewExpressRequest =
            ConvertUtil.copyProperties(sourcePreviewExpressRequest, PreviewExpressRequest.class);
        if (CollectionUtils.isNotEmpty(sourcePreviewExpressRequest.getExpressionParamList())) {
            previewExpressRequest.setExpressionParamList(
                ConvertUtil.copyProperties(
                    sourcePreviewExpressRequest.getExpressionParamList(),
                    PreviewExpressRequest.ExpressionParam.class));
        }
        taskDTO.setPreviewExpressRequest(previewExpressRequest);

        TaskConfigDomain sourceTaskConfigRequest = taskDomain.getTaskConfigRequest();
        HttpTaskDTO.TaskConfigRequest taskConfigRequest =
            ConvertUtil.copyProperties(sourceTaskConfigRequest, HttpTaskDTO.TaskConfigRequest.class);

        taskConfigRequest.setTargetFields(
            ConvertUtil.copyProperties(
                sourceTaskConfigRequest.getTargetFields(),
                HttpTaskDTO.TaskConfigRequest.TargetField.class));
        taskConfigRequest.setFieldMappings(
            ConvertUtil.copyProperties(
                sourceTaskConfigRequest.getFieldMappings(),
                HttpTaskDTO.TaskConfigRequest.FieldMapping.class));
        taskConfigRequest.setPartitions(
            ConvertUtil.copyProperties(
                sourceTaskConfigRequest.getPartitions(),
                HttpTaskDTO.TaskConfigRequest.PartitionField.class));
        taskDTO.setTaskConfigRequest(taskConfigRequest);

        return taskDTO;
    }

    public boolean saveTask(SaveHttpTaskRequest saveTaskRequest) {
        TestApiHttpRequest apiHttpRequest = saveTaskRequest.getApiHttpRequest();
        // 参数转换 请求参数
        TestApiHttpParam testApiHttpParam =
            ConvertUtil.copyProperties(apiHttpRequest, TestApiHttpParam.class);

        // 复制认证参数
        ApiHttpAuthParam apiHttpAuthParam =
            ConvertUtil.copyProperties(apiHttpRequest.getApiHttpAuthParam(), ApiHttpAuthParam.class);
        testApiHttpParam.setApiHttpAuthParam(apiHttpAuthParam);

        TestApiHttpRequest.ApiHttpRequestBodyParam sourceBodyParam =
            apiHttpRequest.getApiHttpRequestBodyParam();

        // 复制type和json
        ApiHttpRequestBodyParam apiHttpRequestBodyParam =
            ConvertUtil.copyProperties(sourceBodyParam, ApiHttpRequestBodyParam.class);

        // 复制参数列表
        if (CollectionUtils.isNotEmpty(sourceBodyParam.getFormParams())) {
            apiHttpRequestBodyParam.setFormParams(
                ConvertUtil.copyProperties(
                    sourceBodyParam.getFormParams(), ApiHttpRequestBodyParam.FormParam.class));
        }
        String jsonBody = apiHttpRequestBodyParam.getBody();
        if (StringUtils.isNotEmpty(jsonBody)) {
            apiHttpRequestBodyParam.setBody(jsonBody.replace("\r\n", ""));
        }
        testApiHttpParam.setApiHttpRequestBodyParam(apiHttpRequestBodyParam);

        // 用户填写的js脚本或者json path
        PreviewExpressRequest previewExpressRequest = saveTaskRequest.getPreviewExpressRequest();
        boolean existJsScript = StringUtils.isNotBlank(previewExpressRequest.getJsScript());
        boolean existJsonPath =
            CollectionUtils.isNotEmpty(previewExpressRequest.getExpressionParamList());
        if (existJsScript == existJsonPath) {
            throw new BusinessException("js脚本和json path必须填写并且只能填写一个");
        }
        PreviewExpressParam previewExpressParam =
            ConvertUtil.copyProperties(previewExpressRequest, PreviewExpressParam.class);
        // 如果填写的是jsonpath,进行复制
        if (existJsonPath) {
            previewExpressParam.setExpressionParamList(
                ConvertUtil.copyProperties(
                    previewExpressRequest.getExpressionParamList(), ExpressionParam.class));
        }

        // 任务其他配置
        TaskConfigRequest taskConfigRequest = saveTaskRequest.getTaskConfigRequest();
        TaskConfigParam taskConfigParam =
            ApiTaskConfigConvert.convertTaskConfigParam(taskConfigRequest);

        ApiHttpSaveParam apiHttpSaveParam = new ApiHttpSaveParam();
        apiHttpSaveParam.setId(saveTaskRequest.getId());
        apiHttpSaveParam.setTaskName(saveTaskRequest.getTaskName());
        apiHttpSaveParam.setTestApiHttpParam(testApiHttpParam);
        apiHttpSaveParam.setPreviewParam(previewExpressParam);
        apiHttpSaveParam.setTask(taskConfigParam);
        apiHttpService.save(apiHttpSaveParam);

        return true;
    }

    public Long reRunTask(Long taskId) {
        return apiHttpService.run(taskId);
    }

    public boolean offlineTask(Long taskId) {
        apiHttpService.operate(taskId, "offline");
        return true;
    }

    public boolean publishTask(Long taskId) {
        apiHttpService.operate(taskId, "online");
        return true;
    }

    public boolean deleteTask(Long taskId) {
        apiHttpService.delete(taskId);
        return true;
    }

    public TestApiDTO test(TestApiHttpRequest testAPiHttpRequest) {
        TestApiHttpParam testApiHttpParam = new TestApiHttpParam();
        testApiHttpParam.setHttpRequestMethod(testAPiHttpRequest.getHttpRequestMethod());
        testApiHttpParam.setUrl(testAPiHttpRequest.getUrl());
        // auth
        testApiHttpParam.setApiHttpAuthParam(
            ConvertUtil.copyProperties(
                testAPiHttpRequest.getApiHttpAuthParam(), ApiHttpAuthParam.class));

        // body
        ApiHttpRequestBodyParam apiHttpRequestBodyParam =
            ConvertUtil.copyProperties(
                testAPiHttpRequest.getApiHttpRequestBodyParam(), ApiHttpRequestBodyParam.class);
        if (CollectionUtils.isNotEmpty(
            testAPiHttpRequest.getApiHttpRequestBodyParam().getFormParams())) {
            apiHttpRequestBodyParam.setFormParams(
                ConvertUtil.copyProperties(
                    testAPiHttpRequest.getApiHttpRequestBodyParam().getFormParams(),
                    ApiHttpRequestBodyParam.FormParam.class));
        }
        String jsonBody = apiHttpRequestBodyParam.getBody();
        if (StringUtils.isNotEmpty(jsonBody)) {
            apiHttpRequestBodyParam.setBody(jsonBody.replace("\r\n", ""));
        }
        testApiHttpParam.setApiHttpRequestBodyParam(apiHttpRequestBodyParam);

        TestApiHttpDomain testApiHttpDomain = apiHttpService.testApiHttp(testApiHttpParam);
        return testApiDTOMapper.map(testApiHttpDomain);
    }

    public UploadJarDTO uploadJar(MultipartFile file) {
        JarUploadResultDomain jarUploadResultDomain = apiHttpService.uploadJar(file);
        return uploadJarDTOMapper.map(jarUploadResultDomain);
    }

    public List<List<Object>> preview(PreviewExpressRequest previewExpressRequest) {
        boolean existJsScript = StringUtils.isNotBlank(previewExpressRequest.getJsScript());
        boolean existJsonPath =
            CollectionUtils.isNotEmpty(previewExpressRequest.getExpressionParamList());
        if (existJsScript == existJsonPath) {
            throw new BusinessException("js脚本和json path必须填写并且只能填写一个");
        }
        PreviewExpressParam previewExpressParam =
            ConvertUtil.copyProperties(previewExpressRequest, PreviewExpressParam.class);
        if (existJsonPath) {
            List<ExpressionParam> expressionParams =
                ConvertUtil.copyProperties(
                    previewExpressRequest.getExpressionParamList(), ExpressionParam.class);
            previewExpressParam.setExpressionParamList(expressionParams);
        }
        List<List<Object>> preview = apiHttpService.preview(previewExpressParam);
        return preview;
    }

    public GetDataSourceDTO getDatabases(Long projectId) {
        List<DataSourceDomain> databases = apiHttpService.getDatabases(projectId);
        var getDataSourceDTO = new GetDataSourceDTO();
        List<GetDataSourceDTO.DataSource> dataSources =
            ConvertUtil.copyProperties(databases, GetDataSourceDTO.DataSource.class);
        getDataSourceDTO.setDataSources(dataSources);
        return getDataSourceDTO;
    }

    public GetTargetTablesDTO getTargetTables(Long dsId) {
        List<TableInfoDomain> targetTables = apiHttpService.getTargetTables(dsId);
        GetTargetTablesDTO getTargetTablesDTO = new GetTargetTablesDTO();
        List<GetTargetTablesDTO.Table> tables =
            ConvertUtil.copyProperties(targetTables, GetTargetTablesDTO.Table.class);
        for (GetTargetTablesDTO.Table table : tables) {
            if (StringUtils.isNotEmpty(table.getSchema())) {
                table.setDetailedTblName(String.format("%s.%s", table.getSchema(), table.getTableName()));
            }
        }
        getTargetTablesDTO.setTables(tables);
        return getTargetTablesDTO;
    }

    public GetCreateTableDDLDTO getCreateTableDDL(GetCreateTableDDLRequest getCreateTableDDLRequest) {
        Long projectId = ServletUtils.getProjectId();
        String createTableDDL =
            apiHttpService.getCreateTableDDL(
                projectId,
                getCreateTableDDLRequest.getDsId(),
                getCreateTableDDLRequest.getFields(),
                getCreateTableDDLRequest.getIsSupportRtf());
        return new GetCreateTableDDLDTO(createTableDDL);
    }

    public String saveTargetTable(SaveTargetTableRequest saveTargetTableRequest) {
        Long projectId = ServletUtils.getProjectId();
        return apiHttpService.saveTargetTable(
            projectId, saveTargetTableRequest.getSql(), saveTargetTableRequest.getDataSecretId());
    }

    public GetFieldsDTO getTargetTableFields(Long dsId, String tableName) {
        List<FieldInfoDomain> targetTableFields = apiHttpService.getTargetTableFields(dsId, tableName);
        GetFieldsDTO getFieldsResponse = new GetFieldsDTO();
        getFieldsResponse.setFields(
            ConvertUtil.copyProperties(targetTableFields, GetFieldsDTO.Field.class));
        return getFieldsResponse;
    }

    public boolean ignoreApiRunningRecord(String ids) {
        return apiHttpService.ignoreApiRunningRecord(ids);
    }

    public PagerResponse<TaskRecordDTO> historyTask(
        Integer pageNum, Integer pageSize, Long taskId, String taskName, String createBy, Integer taskStatus, Integer ignored, Integer executeType) {
        TaskRecordParam taskRecordParam =
            TaskRecordParam.builder()
                .taskId(taskId)
                .taskName(taskName)
                .createBy(createBy)
                .pageNum(pageNum)
                .pageSize(pageSize)
                .taskStatus(taskStatus)
                .executeType(executeType)
                .ignored(ignored)
                .build();
        PageResult<TaskRecordDomain> pageDomain = apiHttpService.historyTask(taskRecordParam);
        return taskRecordDTOPageMapper.toPageResponse(pageDomain);
    }

    public ApiHttpLogDTO getOfflineSyncLog(Long logId, Integer offset) {
        ApiLogDomain logDomain = apiHttpService.getOfflineSyncLog(logId, offset);
        return ConvertUtil.copyProperties(logDomain, ApiHttpLogDTO.class);
    }

    public boolean stopTask(Long logId) {
        apiHttpService.stop(logId);
        return true;
    }
}
